#include "QtGuiEx/RichTextEditor.qth"
#include "QtGuiEx/RichTextEditor.moh"
#include "QtGuiEx/RichTextEditorBar.qth"
#include <QtGui/QTextCharFormat>
#include <QtGui/QTextBlockFormat>
#include <QtGui/QTextListFormat>
#include <QtGui/QTextCursor>
#include <QtGui/QIcon>
#include <QtGui/QTextDocument>
#include <QtGui/QTextCursor>
#include <QtGui/QTextList>
#include <cassert>

namespace QtGuiEx
{

RichTextEditor::RichTextEditor( QWidget* pParent)
	: QTextEdit( pParent)
{
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::connectToBar( RichTextEditorBar* pBar)
{
	assert( NULL != pBar);
	connect( pBar, SIGNAL( boldToggled(bool)), this, SLOT( toggleBold( bool)));
	connect( pBar, SIGNAL( italicToggled(bool)), this, SLOT( toggleItalic( bool)));
	connect( pBar, SIGNAL( underlineToggled(bool)), this, SLOT( toggleUnderline( bool)));
	connect( pBar, SIGNAL( strikeTroughToggled(bool)), this, SLOT( toggleStrikeThrough(bool)));
	
	connect( pBar, SIGNAL( textColorSelected( const QColor&)), this, SLOT( setTextColor( const QColor&)));
	connect( pBar, SIGNAL( backgroundColorSelected( const QColor&)), this, SLOT( setBackgroundColor( const QColor&)));
	
	connect( pBar, SIGNAL( fontFamilySelected(const QString&)), this, SLOT( setFontFamily( const QString&)));
	connect( pBar, SIGNAL( fontSizeSelected( float)), this, SLOT( setFontSize( float)));

	connect( pBar, SIGNAL( paragraphAlignSelected( Qt::Alignment)), this, SLOT( setParagraphAlign( Qt::Alignment)));
	connect( pBar, SIGNAL( paragraphIndented()), this, SLOT( indentParagraph()));
	connect( pBar, SIGNAL( paragraphOutdented()), this, SLOT( outdentParagraph()));

	connect( pBar, SIGNAL( listStyleChanged( QTextListFormat::Style)), this, SLOT( changeListStyle( QTextListFormat::Style)));
	
	connect( this, SIGNAL( currentCharFormatChanged( const QTextCharFormat& )), pBar, SLOT( updateFromCharFormat( const QTextCharFormat&)));
	connect( this, SIGNAL( cursorPositionChanged()), this, SLOT( handleCursorPositionChanged()));
	connect( this, SIGNAL( paragraphFormatChanged( const QTextBlockFormat&, const QTextListFormat& )), pBar, SLOT( updateFromParagraphFormat( const QTextBlockFormat&, const QTextListFormat& )));

	pBar->updateFromCharFormat( this->currentCharFormat());
	pBar->updateFromParagraphFormat( this->textCursor().blockFormat(), QTextListFormat());
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::disconnectFromBar( RichTextEditorBar* pBar)
{
	assert( NULL != pBar);
	disconnect( pBar, 0, this, 0);
	disconnect( this, 0, pBar, 0);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::mergeFormatOnWordOrSelection( const QTextCharFormat& fmt )
{
	QTextCursor cursor = this->textCursor();
	if (!cursor.hasSelection())
		cursor.select(QTextCursor::WordUnderCursor);
	cursor.mergeCharFormat( fmt);
	this->mergeCurrentCharFormat( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::toggleBold( bool bolded)
{
	QTextCharFormat fmt;
	fmt.setFontWeight( bolded ? QFont::Bold : QFont::Normal);
	this->mergeFormatOnWordOrSelection(fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::toggleItalic( bool italic)
{
	QTextCharFormat fmt;
	fmt.setFontItalic( italic);
	this->mergeFormatOnWordOrSelection(fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::toggleUnderline( bool underlined)
{
	QTextCharFormat fmt;
	fmt.setFontUnderline( underlined);
	this->mergeFormatOnWordOrSelection(fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::toggleStrikeThrough( bool striked)
{
	QTextCharFormat fmt;
	fmt.setFontStrikeOut( striked);
	this->mergeFormatOnWordOrSelection( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::setTextColor( const QColor& selectedColor)
{
	QTextCharFormat fmt;
	fmt.setForeground( selectedColor);
	this->mergeFormatOnWordOrSelection( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::setBackgroundColor( const QColor& selectedColor)
{
	QTextCharFormat fmt;
	fmt.setBackground( selectedColor);
	this->mergeFormatOnWordOrSelection( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::setFontFamily( const QString& familyName)
{
	QTextCharFormat fmt;
	fmt.setFontFamily( familyName);
	this->mergeFormatOnWordOrSelection( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::setFontSize( float pointSize)
{
	QTextCharFormat fmt;
	fmt.setFontPointSize( pointSize);
	this->mergeFormatOnWordOrSelection( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::handleCursorPositionChanged()
{
	QTextCursor cursor = this->textCursor();
	QTextList* pCurrentList = cursor.currentList();
	QTextListFormat fmt;
	if( NULL != pCurrentList)
	{
		fmt = pCurrentList->format();
	}
	Q_EMIT paragraphFormatChanged( cursor.blockFormat(), fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::setParagraphAlign( Qt::Alignment newAlignment)
{
	this->setAlignment( newAlignment);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::indentParagraph()
{
	QTextCursor cursor = this->textCursor();
	QTextBlockFormat fmt = cursor.blockFormat();
	fmt.setIndent( fmt.indent() + 1);
	cursor.setBlockFormat( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::outdentParagraph()
{
	QTextCursor cursor = this->textCursor();
	QTextBlockFormat fmt = cursor.blockFormat();
	int curIndent = fmt.indent();
	if( curIndent == 0) return;
	fmt.setIndent( curIndent - 1);
	cursor.setBlockFormat( fmt);
}

// ---------------------------------------------------------------------------------------------------------------------

void RichTextEditor::changeListStyle( QTextListFormat::Style newStyle)
{
	QTextCursor cursor = this->textCursor();
	QTextList* pList = NULL;
	if( QTextListFormat::ListStyleUndefined == newStyle)
	{
		pList = cursor.currentList();
		if( NULL == pList) return;
		QTextListFormat fmt = pList->format();
		fmt.setStyle( QTextListFormat::ListStyleUndefined);
		pList->setFormat( fmt);
	}
	else
	{
		cursor.createList( newStyle);
	}
}

} // namespace QtGuiEx
